import atexit
from pyVim import connect
from pyVmomi import vmodl
from pyVmomi import vim
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

# 连接vCenter
def vcenter_connect(vcenter_host, vcenter_user, vcenter_password):
    try:
        service_instance = connect.SmartConnect(
            host=vcenter_host,
            user=vcenter_user,
            pwd=vcenter_password,
            disableSslCertValidation=True  # 在测试环境中可以禁用SSL证书验证
        )
        return service_instance
    except vim.fault.InvalidLogin as e:
        print(f"登录失败: {str(e)}")
        raise
    except Exception as e:
        print(f"连接vCenter时发生错误: {str(e)}")
        raise

# 关闭vCenter连接
def vcenter_disconnect(service_instance):
    try:
        connect.Disconnect(service_instance)
    except Exception as e:
        print(f"断开连接时发生错误: {str(e)}")

# 获取数据中心信息
def get_datacenter(service_instance):
    # ...
    return datacenter

# 获取计算资源(群集或主机)
def get_compute_resource(datacenter):
    # ...
    return compute_resource

# 获取数据存储 
def get_datastore(datacenter):
    # ...
    return datastore

# 获取虚拟机文件夹
def get_vm_folder(datacenter):
    # ...
    return vm_folder

# 部署虚拟机
def deploy_virtual_machine(service_instance, vm_name, vm_template_name, datacenter_name, 
                           compute_resource_name, datastore_name):
    # ...
    pass
    
# 获取计算资源信息
def get_compute_resources(service_instance):
    try:
        content = service_instance.RetrieveContent()
        container = content.rootFolder
        view_type = [vim.ComputeResource]
        recursive = True
        
        container_view = content.viewManager.CreateContainerView(
            container, view_type, recursive
        )
        
        compute_resources = []
        for compute in container_view.view:
            resource_info = {
                'name': compute.name,
                'total_cpu': compute.summary.totalCpu,
                'total_memory': compute.summary.totalMemory // (1024*1024*1024),  # 转换为GB
                'free_cpu': compute.summary.effectiveCpu,
                'free_memory': compute.summary.effectiveMemory // 1024,  # 转换为GB
                'object': compute
            }
            compute_resources.append(resource_info)
            
        container_view.Destroy()
        return compute_resources
    except Exception as e:
        raise Exception(f"获取计算资源失败: {str(e)}")

# 获取存储信息
def get_datastores(service_instance):
    try:
        content = service_instance.RetrieveContent()
        container = content.rootFolder
        view_type = [vim.Datastore]
        recursive = True
        
        container_view = content.viewManager.CreateContainerView(
            container, view_type, recursive
        )
        
        datastores = []
        for ds in container_view.view:
            ds_info = {
                'name': ds.name,
                'total_space': ds.summary.capacity // (1024*1024*1024),  # 转换为GB
                'free_space': ds.summary.freeSpace // (1024*1024*1024),  # 转换为GB
                'object': ds
            }
            datastores.append(ds_info)
            
        container_view.Destroy()
        return datastores
    except Exception as e:
        raise Exception(f"获取存储资源失败: {str(e)}")

# 创建GUI
def create_gui():
    # 创建主窗口
    root = tk.Tk()
    root.title("vCenter自动化部署工具")
    root.geometry("400x300")  # 设置窗口大小
    
    # 创建输入框和标签
    tk.Label(root, text="vCenter服务器地址:").pack(pady=5)
    host_entry = tk.Entry(root)
    host_entry.pack(pady=5)
    
    tk.Label(root, text="用户名:").pack(pady=5)
    user_entry = tk.Entry(root)
    user_entry.pack(pady=5)
    
    tk.Label(root, text="密码:").pack(pady=5)
    password_entry = tk.Entry(root, show="*")  # 密码显示为*
    password_entry.pack(pady=5)
    
    # 连接按钮点击事件处理
    def connect_clicked():
        try:
            host = host_entry.get()
            user = user_entry.get()
            password = password_entry.get()
            
            if not (host and user and password):
                tk.messagebox.showerror("错误", "请填写所有字段")
                return
                
            print(f"正在连接到vCenter服务器: {host}")
            service_instance = vcenter_connect(host, user, password)
            
            # 连接成功后显示部署界面
            show_deploy_gui(root, service_instance)
            
        except Exception as e:
            tk.messagebox.showerror("错误", f"连接失败: {str(e)}")
    
    # 添加连接按钮
    connect_button = ttk.Button(root, text="连接", command=connect_clicked)
    connect_button.pack(pady=20)
    
    return root

# 修改显示部署界面函数
def show_deploy_gui(root, service_instance):
    # 清空当前窗口
    for widget in root.winfo_children():
        widget.destroy()
    
    # 创建左右分栏
    left_frame = ttk.Frame(root)
    left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10)
    
    right_frame = ttk.Frame(root)
    right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10)
    
    # 左侧 - 资源信息显示
    ttk.Label(left_frame, text="可用资源信息", font=('Arial', 12, 'bold')).pack(pady=5)
    
    # 计算资源信息
    compute_resources = get_compute_resources(service_instance)
    ttk.Label(left_frame, text="计算资源:").pack(pady=5)
    compute_text = tk.Text(left_frame, height=6, width=30)
    compute_text.pack(pady=5)
    for cr in compute_resources:
        compute_text.insert(tk.END, 
            f"节点: {cr['name']}\n"
            f"CPU: {cr['free_cpu']}/{cr['total_cpu']} MHz\n"
            f"内存: {cr['free_memory']}/{cr['total_memory']} GB\n"
            f"------------------------\n"
        )
    compute_text.config(state='disabled')
    
    # 存储资源信息
    datastores = get_datastores(service_instance)
    ttk.Label(left_frame, text="存储资源:").pack(pady=5)
    storage_text = tk.Text(left_frame, height=6, width=30)
    storage_text.pack(pady=5)
    for ds in datastores:
        storage_text.insert(tk.END,
            f"存储: {ds['name']}\n"
            f"可用空间: {ds['free_space']}/{ds['total_space']} GB\n"
            f"------------------------\n"
        )
    storage_text.config(state='disabled')
    
    # 右侧 - 部署配置
    ttk.Label(right_frame, text="部署配置", font=('Arial', 12, 'bold')).pack(pady=5)
    
    ttk.Label(right_frame, text="虚拟机名称:").pack(pady=5)
    vm_name_entry = ttk.Entry(right_frame)
    vm_name_entry.pack(pady=5)
    
    ttk.Label(right_frame, text="模板名称:").pack(pady=5)
    template_entry = ttk.Entry(right_frame)
    template_entry.pack(pady=5)
    
    ttk.Label(right_frame, text="选择计算节点:").pack(pady=5)
    compute_var = tk.StringVar()
    compute_combo = ttk.Combobox(right_frame, textvariable=compute_var)
    compute_combo['values'] = [cr['name'] for cr in compute_resources]
    compute_combo.pack(pady=5)
    
    ttk.Label(right_frame, text="CPU (MHz):").pack(pady=5)
    cpu_entry = ttk.Entry(right_frame)
    cpu_entry.pack(pady=5)
    
    ttk.Label(right_frame, text="内存 (GB):").pack(pady=5)
    memory_entry = ttk.Entry(right_frame)
    memory_entry.pack(pady=5)
    
    ttk.Label(right_frame, text="选择存储:").pack(pady=5)
    storage_var = tk.StringVar()
    storage_combo = ttk.Combobox(right_frame, textvariable=storage_var)
    storage_combo['values'] = [ds['name'] for ds in datastores]
    storage_combo.pack(pady=5)
    
    ttk.Label(right_frame, text="磁盘空间 (GB):").pack(pady=5)
    disk_entry = ttk.Entry(right_frame)
    disk_entry.pack(pady=5)
    
    # 部署按钮点击事件处理
    def deploy_clicked():
        try:
            # 获取输入值
            vm_name = vm_name_entry.get()
            template_name = template_entry.get()
            compute_name = compute_var.get()
            storage_name = storage_var.get()
            cpu = cpu_entry.get()
            memory = memory_entry.get()
            disk = disk_entry.get()
            
            # 验证所有字段都已填写
            if not all([vm_name, template_name, compute_name, storage_name, cpu, memory, disk]):
                tk.messagebox.showerror("错误", "请填写所有字段")
                return
            
            # 验证资源是否足够
            selected_compute = next((cr for cr in compute_resources if cr['name'] == compute_name), None)
            selected_storage = next((ds for ds in datastores if ds['name'] == storage_name), None)
            
            if not selected_compute or not selected_storage:
                tk.messagebox.showerror("错误", "请选择有效的计算节点和存储")
                return
                
            if int(cpu) > selected_compute['free_cpu']:
                tk.messagebox.showerror("错误", "CPU资源不足")
                return
                
            if int(memory) > selected_compute['free_memory']:
                tk.messagebox.showerror("错误", "内存资源不足")
                return
                
            if int(disk) > selected_storage['free_space']:
                tk.messagebox.showerror("错误", "存储空间不足")
                return
            
            # 调用部署函数
            deploy_virtual_machine(service_instance, vm_name, template_name,
                                 compute_name, storage_name, cpu, memory, disk)
            
            tk.messagebox.showinfo("成功", "虚拟机部署已启动")
            
        except Exception as e:
            tk.messagebox.showerror("错误", f"部署失败: {str(e)}")
    
    # 添加部署按钮
    deploy_button = ttk.Button(right_frame, text="部署", command=deploy_clicked)
    deploy_button.pack(pady=20)

def main():
    try:
        root = create_gui()
        root.mainloop()
    except Exception as e:
        print(f"程序运行出错: {str(e)}")
        return

if __name__ == "__main__":
    main() 